home *** CD-ROM | disk | FTP | other *** search
- #!/bin/bash
- # Copyright 1999-2005 Gentoo Foundation
- # Distributed under the terms of the GNU General Public License v2
- # $Header$
-
- # Common functions
- [[ ${RC_GOT_FUNCTIONS} != "yes" ]] && source /sbin/functions.sh
- # Functions to handle dependencies and services
- [[ ${RC_GOT_SERVICES} != "yes" ]] && source "${svclib}/sh/rc-services.sh"
- # Functions to control daemons
- [[ ${RC_GOT_DAEMON} != "yes" ]] && source "${svclib}/sh/rc-daemon.sh"
-
- # User must be root to run most script stuff (except status)
- if [[ ${EUID} != 0 ]] && ! [[ $2 == "status" && $# -eq 2 ]] ; then
- eerror "$0: must be root to run init scripts"
- exit 1
- fi
-
- # Stop init scripts from working until sysinit completes
- if [[ -e /dev/.rcsysinit ]] ; then
- eerror "ERROR: cannot run ${myservice} until sysinit completes"
- exit 1
- fi
-
- # State variables
- svcpause="no"
- svcrestart="no"
-
- myscript="$1"
- if [[ -L $1 ]] && [[ ! -L /etc/init.d/${1##*/} ]] ; then
- myservice=$(readlink "$1")
- else
- myservice=$1
- fi
-
- myservice=${myservice##*/}
- export SVCNAME=${myservice}
- mylevel=$(<"${svcdir}/softlevel")
-
-
- # Set $IFACE to the name of the network interface if it is a 'net.*' script
- if [[ ${myservice%%.*} == "net" ]] && [[ ${myservice##*.} != ${myservice} ]] ; then
- IFACE=${myservice##*.}
- NETSERVICE="yes"
- else
- IFACE=
- NETSERVICE=
- fi
-
- # We need to stop hotplug from launching net scripts until the boot level
- # has completed
- if [[ ${NETSERVICE} == "yes" && ${IFACE} != "lo" ]] ; then
- if [[ -z ${mylevel} || ${mylevel} == ${BOOTLEVEL} ]] ; then
- eerror "${myservice}: cannot start until the runlevel ${BOOTLEVEL} has completed"
- exit 1
- fi
- fi
-
- # Source configuration files.
- # (1) Source /etc/conf.d/${myservice} to get initscript-specific
- # configuration (if it exists).
- # (2) Source /etc/conf.d/net if it is a net.* service
- # (3) Source /etc/rc.conf to pick up potentially overriding
- # configuration, if the system administrator chose to put it
- # there (if it exists).
-
- [[ -e $(add_suffix /etc/conf.d/${myservice}) ]] && source "$(add_suffix /etc/conf.d/${myservice})"
- [[ -e $(add_suffix /etc/conf.d/net) ]] && \
- [[ ${NETSERVICE} == "yes" ]] && source "$(add_suffix /etc/conf.d/net)"
- [[ -e $(add_suffix /etc/rc.conf) ]] && source "$(add_suffix /etc/rc.conf)"
-
-
- usage() {
- local IFS="|"
- myline="Usage: ${myservice} { $* "
- echo
- eerror "${myline}}"
- eerror " ${myservice} without arguments for full help"
- }
-
- stop() {
- # Return success so the symlink gets removed
- return 0
- }
-
- start() {
- eerror "ERROR: \"${myservice}\" does not have a start function."
- # Return failure so the symlink doesn't get created
- return 1
- }
-
- restart() {
- svc_restart || return $?
- }
-
- status() {
- # Dummy function
- return 0
- }
-
- svc_stop() {
- local x=
- local mydep=
- local mydeps=
- local retval=0
- local ordservice=
-
- if ! service_started "${myservice}" ; then
- if [[ ${RC_QUIET_STDOUT} != "yes" ]] ; then
- eerror "ERROR: \"${myservice}\" has not yet been started."
- fi
- return 0
- fi
-
- # Do not try to stop if it had already failed to do so on runlevel change
- if is_runlevel_stop && service_failed "${myservice}" ; then
- exit 1
- fi
-
- # Remove symlink to prevent recursion
- mark_service_stopped "${myservice}"
-
- if in_runlevel "${myservice}" "${BOOTLEVEL}" && \
- [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" && ${SOFTLEVEL} != "single" ]]
- then
- ewarn "WARNING: you are stopping a boot service."
- fi
-
- if [[ ${svcpause} != "yes" && ${RC_NODEPS} != "yes" ]] ; then
- if [[ ${NETSERVICE} == "yes" ]] ; then
- # A net.* service
- if in_runlevel "${myservice}" "${BOOTLEVEL}" || \
- in_runlevel "${myservice}" "${mylevel}"
- then
- # Only worry about net.* services if this is the last one running,
- # or if RC_NET_STRICT_CHECKING is set ...
- if ! is_net_up ; then
- mydeps="net"
- fi
- fi
-
- mydeps="${mydeps} ${myservice}"
- else
- mydeps="${myservice}"
- fi
- fi
-
- for mydep in ${mydeps} ; do
- # If some service 'need' $mydep, stop it first; or if it is a runlevel change,
- # first stop all services that is started 'after' $mydep.
- if needsme "${mydep}" >/dev/null || \
- (is_runlevel_stop && ibefore "${mydep}" >/dev/null)
- then
- local servicelist="$(needsme "${mydep}")"
-
- # On runlevel change, stop all services "after $mydep" first ...
- is_runlevel_stop && servicelist="${servicelist} $(ibefore "${mydep}")"
-
- for x in ${servicelist} ; do
- # Make sure we have a relevant rc-script ...
- if [[ ${x} != "net" && ! -f /etc/init.d/${x} ]] ; then
- continue
- fi
-
- # Service not currently running, continue
- service_started "${x}" || continue
-
- if ibefore -t "${mydep}" "${x}" >/dev/null && \
- [[ -L ${svcdir}/softscripts.new/${x} ]]
- then
- # Service do not 'need' $mydep, and is still present in
- # new runlevel ...
- continue
- fi
-
- stop_service "${x}"
-
- if [[ $? -ne 0 ]] ; then
- # If we are halting the system, try and get it down as
- # clean as possible, else do not stop our service if
- # a dependent service did not stop.
- if needsme -t "${mydep}" "${x}" >/dev/null && \
- [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" ]]
- then
- retval=1
- fi
-
- break
- fi
- done
- fi
- done
-
- if [[ ${retval} -ne 0 ]] ; then
- eerror "ERROR: problems stopping dependent services."
- eerror " \"${myservice}\" is still up."
- else
- # Now that deps are stopped, stop our service
- stop
- retval="$?"
- fi
-
- if [[ ${retval} -ne 0 ]] ; then
- # Did we fail to stop? create symlink to stop multible attempts at
- # runlevel change. Note this is only used at runlevel change ...
- if is_runlevel_stop ; then
- mark_service_failed "${myservice}"
- fi
-
- # If we are halting the system, do it as cleanly as possible
- if [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" ]] ; then
- mark_service_started "${myservice}"
- fi
- fi
-
- return "${retval}"
- }
-
- svc_start() {
- local retval=0
- local startfail="no"
- local x=
- local y=
- local myserv=
- local ordservice=
-
- if ! service_started "${myservice}" ; then
- # Do not try to start if i have done so already on runlevel change
- if is_runlevel_start && service_failed "${myservice}" ; then
- exit 1
- fi
-
- # Link first to prevent possible recursion
- mark_service_started "${myservice}"
-
- # On rc change, start all services "before $myservice" first
- if [[ ${RC_NODEPS} != "yes" ]] ; then
- if is_runlevel_start ; then
- startupservices="$(ineed "${myservice}") \
- $(valid_iuse "${myservice}") \
- $(valid_iafter "${myservice}")"
- else
- startupservices="$(ineed "${myservice}") \
- $(valid_iuse "${myservice}")"
- fi
- fi
-
- # Start dependencies, if any
- for x in ${startupservices} ; do
- if [[ ${x} == "net" && ${NETSERVICE} != "yes" ]] && ! is_net_up ; then
- local netservices="$(dolisting "/etc/runlevels/${BOOTLEVEL}/net.*") \
- $(dolisting "/etc/runlevels/${mylevel}/net.*")"
-
- for y in ${netservices} ; do
- mynetservice="${y##*/}"
-
- if ! service_started "${mynetservice}" ; then
- start_service "${mynetservice}"
-
- # A 'need' dependency is critical for startup
- if [[ $? -ne 0 ]] && ineed -t "${myservice}" "${x}" >/dev/null ; then
- # Only worry about a net.* service if we do not have one
- # up and running already, or if RC_NET_STRICT_CHECKING
- # is set ....
- if ! is_net_up ; then
- startfail="yes"
- fi
- fi
- fi
- done
-
- elif [[ ${x} != "net" ]] ; then
- if ! service_started "${x}" ; then
- start_service "${x}"
-
- # A 'need' dependacy is critical for startup
- if [[ $? -ne 0 ]] && ineed -t "${myservice}" "${x}" >/dev/null ; then
- startfail="yes"
- fi
- fi
- fi
- done
-
- if [[ ${startfail} == "yes" ]] ; then
- eerror "ERROR: Problem starting needed services."
- eerror " \"${myservice}\" was not started."
- retval=1
- fi
-
- # Start service
- if [[ ${retval} -eq 0 ]] && broken "${myservice}" ; then
- eerror "ERROR: Some services needed are missing. Run"
- eerror " './${myservice} broken' for a list of those"
- eerror " services. \"${myservice}\" was not started."
- retval=1
- elif [[ ${retval} -eq 0 ]] && ! broken "${myservice}" ; then
- (
- exit() {
- eerror "DO NOT USE EXIT IN INIT.D SCRIPTS"
- eerror "This IS a bug, please fix your broken init.d"
- unset -f exit
- exit $@
- }
- start
- )
- retval="$?"
- fi
-
- if [[ ${retval} -ne 0 ]] && is_runlevel_start ; then
- mark_service_failed "${myservice}"
- fi
-
- # Remove link if service didn't start; but only if we're not booting
- # if we're booting, we need to continue and do our best to get the
- # system up.
- if [[ ${retval} -ne 0 && ${SOFTLEVEL} != ${BOOTLEVEL} ]] ; then
- mark_service_stopped "${myservice}"
- fi
-
- return "${retval}"
- else
- if [[ ${RC_QUIET_STDOUT} != "yes" ]] ; then
- ewarn "WARNING: \"${myservice}\" has already been started."
- fi
-
- return 0
- fi
- }
-
- svc_restart() {
- if service_started "${myservice}" ; then
- svc_stop || return "$?"
- sleep 1
- fi
-
- svc_start || return "$?"
- }
-
- svc_status() {
- # The basic idea here is to have some sort of consistent
- # output in the status() function which scripts can use
- # as an generic means to detect status. Any other output
- # should thus be formatted in the custom status() function
- # to work with the printed " * status: foo".
- local efunc="" state=""
-
- if service_started "${myservice}" ; then
- efunc="einfo"
- state="started"
- else
- efunc="eerror"
- state="stopped"
- fi
- [[ ${RC_QUIET_STDOUT} != "yes" ]] \
- && ${efunc} "status: ${state}"
-
- status
- [[ ${efunc} != "eerror" ]]
- }
-
- rcscript_errors=$(bash -n "${myscript}" 2>&1) || {
- [[ -n ${rcscript_errors} ]] && echo "${rcscript_errors}" >&2
- eerror "ERROR: \"${myscript}\" has syntax errors in it; not executing..."
- exit 1
- }
-
- # set *after* wrap_rcscript, else we get duplicates.
- opts=""
-
- source "${myscript}"
-
- # make sure whe have valid $opts
- opts="start stop restart pause zap ${opts}"
-
- svc_homegrown() {
- local x arg=$1
- shift
-
- # Walk through the list of available options, looking for the
- # requested one.
- for x in ${opts} ; do
- if [[ ${x} == "${arg}" ]] ; then
- if typeset -F "${x}" &>/dev/null ; then
- # Run the homegrown function
- "${x}"
-
- return $?
- fi
- fi
- done
- x=""
-
- # If we're here, then the function wasn't in $opts.
- [[ -n $* ]] && x="/ $* "
- eerror "ERROR: wrong args ( "${arg}" ${x})"
- # Do not quote this either ...
- usage ${opts}
- exit 1
- }
-
- shift
- if [[ $# -lt 1 ]] ; then
- eerror "ERROR: not enough args."
- usage ${opts}
- exit 1
- fi
- for arg in $* ; do
- case "${arg}" in
- --quiet)
- RC_QUIET_STDOUT="yes"
- ;;
- # We check this in functions.sh ...
- # --nocolor)
- # RC_NOCOLOR="yes"
- # ;;
- --verbose)
- RC_VERBOSE="yes"
- ;;
- --nodeps)
- RC_NODEPS="yes"
- esac
- done
- for arg in $* ; do
- case "${arg}" in
- stop)
- svc_stop
- ;;
- start)
- svc_start
- ;;
- needsme|ineed|usesme|iuse|broken)
- list_depend_trace "${arg}"
- ;;
- status)
- svc_status
- ;;
- zap)
- if service_started "${myservice}" ; then
- einfo "Manually resetting ${myservice} to stopped state."
- mark_service_stopped "${myservice}"
- fi
- ;;
- restart)
- svcrestart="yes"
-
- # Create a snapshot of started services
- rm -rf "${svcdir}/snapshot/$$"
- mkdir -p "${svcdir}/snapshot/$$"
- cp -a "${svcdir}"/started/* "${svcdir}/snapshot/$$/"
-
- # Simple way to try and detect if the service use svc_{start,stop}
- # to restart if it have a custom restart() funtion.
- if [[ -n $(egrep '^[[:space:]]*restart[[:space:]]*()' "/etc/init.d/${myservice}") ]] ; then
- if [[ -z $(egrep 'svc_stop' "/etc/init.d/${myservice}") || \
- -z $(egrep 'svc_start' "/etc/init.d/${myservice}") ]]
- then
- echo
- ewarn "Please use 'svc_stop; svc_start' and not 'stop; start' to"
- ewarn "restart the service in its custom 'restart()' function."
- ewarn "Run ${myservice} without arguments for more info."
- echo
- svc_restart
- else
- restart
- fi
- else
- restart
- fi
-
- # Restart dependencies as well
- if service_started "${myservice}" ; then
- for x in $(dolisting "${svcdir}/snapshot/$$/") ; do
- if ! service_started "${x##*/}" ; then
- # schedule_service_startup "${x##*/}"
- start_service "${x##*/}"
- fi
- done
- fi
-
- # Wait for any services that may still be running ...
- # [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && wait
-
- rm -rf "${svcdir}/snapshot/$$"
- svcrestart="no"
- ;;
- pause)
- svcpause="yes"
- svc_stop
- svcpause="no"
- ;;
- --quiet|--nocolor|--nodeps)
- ;;
- help)
- exec "${svclib}"/sh/rc-help.sh "${myscript}" help
- ;;
- *)
- # Allow for homegrown functions
- svc_homegrown ${arg}
- ;;
- esac
- done
-
-
- # vim:ts=4
-